package com.aube.rvi.statistic;

import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

import com.aube.rvi.CommonDataLoader;
import com.aube.rvi.module.ModuleManager;
import com.aube.rvi.net.AubeError;
import com.aube.rvi.net.ResponseListener;
import com.aube.rvi.net.StringRequest;
import com.aube.rvi.util.StringUtils;
import com.aube.rvi.util.Utils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;

/**
 * Created by huyaonan on 16/10/27.
 */
public class AubeDatabaseHelper {

    private static AubeDatabaseHelper mInstance;
    private AubeDatabase mHelper;
    private Context context;

    private static final String TABLE_NAME = "t_statistic";
    private static final String CACHE_DIR = "aube-statistic";
    private static final String FILE_PREFIX = "aube-";
    private static final String DB_NAME = "aubesdk.db";

    private AubeDatabaseHelper(Context context) {
        mHelper = new AubeDatabase(context, DB_NAME, null, 2);

        this.context = context;
    }

    public void upload() {
        if(isWifiConnected(context)) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        final String result = export();
                        reportFile(result, new OnReportListener() {
                            @Override
                            public void onStart() {
                                clear();
                            }

                            @Override
                            public void onSuccess() {

                            }

                            @Override
                            public void onFail() {
                                saveToFile(result);
                            }
                        });
                        reportFiles();
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

    public interface OnReportListener {
        public void onStart();
        public void onSuccess();
        public void onFail();
    }

    private void reportFile(String result, final OnReportListener listener) {
        if(StringUtils.isBlank(result))
            return;
        Utils.sysout("-----reportdata:" + result);
        HashMap<String, String> basicData = new HashMap<>();
        basicData.put("method", "com.aube.app.event.report");
        basicData.put("formData", result);
        StringRequest request = new StringRequest(ModuleManager.API_ROUTE, basicData, new ResponseListener<String>() {
            @Override
            public void onResponse(String response) {
                Utils.sysout("-----response");
                try {
                    JSONObject result = new JSONObject(response);
                    String code = result.optString("code");
                    String errormsg = result.optString("errormsg");
                    Utils.sysout("-----response:" + code + "/" + errormsg);
                    if("0000".equalsIgnoreCase(code)) {
                        //if success
                        listener.onSuccess();
                        return;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                //if fail, do nothing
                listener.onFail();
            }

            @Override
            public void onErrorResponse(AubeError error) {
                Utils.Log("statistics upload fail, delete the data");
                listener.onFail();
            }

            @Override
            public void onStart() {
                Utils.Log("onStart statistics");
                listener.onStart();
            }
        });

        CommonDataLoader.getInstance(context).startHttpLoader(request);
    }

    private boolean isWifiConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo.State wifiState = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
        if(wifiState != null || NetworkInfo.State.CONNECTED == wifiState)
            return true;
        return false;
    }

    public static synchronized AubeDatabaseHelper getInstance(Context context) {
        if(mInstance == null) {
            mInstance = new AubeDatabaseHelper(context);
        }
        return mInstance;
    }

    public void report(String key, String value) {
        SQLiteDatabase db = mHelper.getWritableDatabase();
        db.execSQL("insert into " + TABLE_NAME + "(key, value, ts) values(?,?,?)", new Object[]{key, value, System.currentTimeMillis()+""});
        db.close();
    }

    private void clear() {
        SQLiteDatabase db = mHelper.getWritableDatabase();
        db.execSQL("DELETE FROM \'" + TABLE_NAME + "\'");
        db.close();
    }

    /**
     * WARNING!!!
     * DO IT ASYNCHRONOUSLY
     */
    private String export() throws JSONException {
        String result = "";
        SQLiteDatabase db = mHelper.getReadableDatabase();
        Cursor cursor = db.rawQuery("select key, value, ts from " + TABLE_NAME, null);
        if(cursor != null) {
            JSONArray data = new JSONArray();
            while (cursor.moveToNext()) {
                String key = cursor.getString(0);
                String value = cursor.getString(1);
                String ts = cursor.getString(2);

                JSONObject item = new JSONObject();
                item.put("event", key);
                item.put("value", value);
                item.put("ts", ts);
                data.put(item);
            }
            cursor.close();
            if(data.length() > 0)
                result = data.toString();
        }
        db.close();
        return result;
    }

    private void reportFiles() {
        try {
            File file = context.getDir(CACHE_DIR, Context.MODE_PRIVATE);
            if(file.exists() && file.listFiles() != null) {
                for(final File item : file.listFiles()) {
                    Utils.sysout("------------file:" + item.getPath());
                    FileInputStream inputStream = new FileInputStream(item);
                    ByteArrayOutputStream os = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    int count = 0;
                    while ((count = inputStream.read(buffer)) != -1) {
                        os.write(buffer, 0, count);
                    }
                    String result = os.toString();
                    os.close();
                    reportFile(result, new OnReportListener() {
                        @Override
                        public void onStart() {

                        }

                        @Override
                        public void onSuccess() {
                            item.delete();
                        }

                        @Override
                        public void onFail() {

                        }
                    });
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void saveToFile(String result) {
        if(StringUtils.isNotBlank(result)) {
            try {
                File file = new File(context.getDir(CACHE_DIR, Context.MODE_PRIVATE), FILE_PREFIX + System.currentTimeMillis());
                FileOutputStream os = new FileOutputStream(file);
                ByteArrayInputStream in = new ByteArrayInputStream(result.getBytes());
                byte[] buffer = new byte[1024];
                int count = 0;
                while ((count = in.read(buffer)) != -1) {
                    os.write(buffer, 0, count);
                }
                os.flush();
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private class AubeDatabase extends SQLiteOpenHelper {

        public AubeDatabase(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
        }

        public AubeDatabase(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
            super(context, name, factory, version, errorHandler);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("create table t_statistic(id integer primary key autoincrement,key varchar(200),value varchar(200),ts varchar(200) )");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("drop table t_statistic");
            onCreate(db);
        }
    }

}
